﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Moki.Examples.Model;

namespace Moki.Examples
{
    [TestFixture]
    public class MokiCustomArguments
    {
        [Test]
        public void SpecifyWithCustomArg()
        {
            // Arrange
            IBookingDB database = Mock.Create<IBookingDB>();
            CinemaBookingService bookingService = new CinemaBookingService(database);

            DateTime today = DateTime.Now;
            DateTime nextWeek = today.AddDays(7);

            Show todayShow = new Show();
            todayShow.DateAndHour = today;

            Show nextWeekShow = new Show();
            nextWeekShow.DateAndHour = nextWeek;

            // Act

            // For today Show all places are booked 
            Mock.WhenCalled(() => 
                database.IsBooked(Arg.Matches<Show>(s => s.DateAndHour.Day == today.Day), Arg.Any<int>())).
                Returns(true);

            // For Show show on next week only first 20 places are booked 
            Mock.WhenCalled(() => 
                database.IsBooked(Arg.Matches<Show>(s => s.DateAndHour.Day == nextWeek.Day), Arg.Matches<int> (i => i <= 20))).
                Returns(true);
            

            // Assert
            Assert.AreEqual(true,   database.IsBooked(todayShow, 1));
            Assert.AreEqual(true, database.IsBooked(todayShow, 2));
            Assert.AreEqual(true, database.IsBooked(todayShow, 100));

            Assert.AreEqual(true, database.IsBooked(nextWeekShow, 19));
            Assert.AreEqual(false, database.IsBooked(nextWeekShow, 21));

        }

        [Test]
        public void VerifyWithCustomArg()
        {
            // Arrange
            IBookingDB database = Mock.Create<IBookingDB>();
            CinemaBookingService bookingService = new CinemaBookingService(database);

            Show show = new Show();

            // Act
            for (int i = 0; i < 10; i++)
            {
                bookingService.BookPlace(show, i, "Jan Kowalski");
            }

            // Assert
            Mock.VerifyCalled(() => database.Book(show, Arg.Any<int>(), "Jan Kowalski"),
                Times.Exactly(10));

            Mock.VerifyCalled(() => database.Book(show, Arg.Matches<int>(i => i < 5), "Jan Kowalski"),
                Times.Exactly(5));
        }
    }
}
